Github Actionsの個人的ユースケース備忘録
はじめに
Github Actionsで色々なフローの自動化に取り組んで一番大変だと感じているのは、目的とするデータをコンテキストのどこから取れるのか見つけるところです。
公式ドキュメントも正直目的の情報に辿り着きやすいとも言えず、StackOverFlow等のFAQフォーラムも類似した質問が多くありすぎて逆に絞るのが大変となる繰り返しでした。
私自身で頻繁に用いそうなものを中心に、調査の手間を省くために備忘録として書き出してみました。2020年5月26時点のデータとなります。
各コンテキストについて
利用可能なコンテキストは以下の8つです。公式ドキュメントが個人的にやや見難いため、必要なところだけを抜粋しました。
- github
- workflowの情報にアクセスする用途
- env
- workflow、job、stepの環境変数にアクセスする用途
- job
- jobの情報にアクセスする用途
- steps
- jobで設定しているstepの情報にアクセスする用途
- runner
- jobを実行しているrunner(セルフホスト含)にアクセスする用途
- secrets
- リポジトリのsecretsにアクセスする用途
- strategy
- strategyパラメータにアクセスする用途(
fail-fast
,job-index
,job-total
,max-parallel
) - matrix
- 実行中のjobに対して決定したmatrixパラメータにアクセスする用途
- needs
- 実行中のjobが依存しているjobによる出力へアクセスする用途
githubやenvについては利用頻度も高いため覚えやすいかと思われます。
用途別のコンテキスト参照
各コンテキストには沢山の要素がありますが、目的を達成するのに使えるのか、及び使っても問題ないのかは正直分かりにくいところです。
頻度が高かったケースを順に書き出しました。
pull-requestのベースブランチ及び比較ブランチを取得する
ベースブランチ、比較ブランチと書くと分かり難いですが、github上で以下の状態になる組み合わせです。
- ベースブランチ(base)
github.base_ref
- 比較ブランチ(compare)
github.head_ref
ポイントは、workflowを実行したイベントがpull_request
の時しか使えません。
on: pull_request: branches: - master jobs: build: runs-on: ubuntu-latest steps: - run: | echo ${{github.base_ref}} echo ${{github.head_ref}}
pull-requestのmergeが完了した時に動作させる
if
への条件指定を用います。stepsでも指定可能ですが、jobそのものに指定することで動作時間の節約を見込めます。
on: pull_request: types: [closed] jobs: build: if: github.event.pull_request.merged == true runs-on: ubuntu-latest steps: - name: merged run: echo merged
jobの実行に順番を持たせる
依存関係を持たせます。
jobs: build: test: needs:[build] release: needs:[build, test]
分けるメリットとしては、buildが失敗したらその時点で終わらせる、といった分岐がif
にて環境変数等を使う必要なく可能になります。
複数の異なる条件で動くjobを一つのファイルに収める
互いに関連するjobは一つのファイルにしたほうが把握しやすいケースもあります。
気をつけるべき点として、on
で指定された条件がjob
に紐づくわけではありません。制約がなければ、いずれのjobもon
に該当する場合必ず実行されます。よって、if
等で正確に指定しなければ事故の原因に繋がります。
on: push: branches_ignore: - master pull_request: branches: - master jobs: pr: if: github.event_name == 'pull_request' test: if: github.event_name == 'push'
pull-requestのmergeでreleaseを作成しつつrelease-messageにpull-requestの文面を流用する
pull-requestでreviewerによる承認を得て、mergeと同時にreleaseを作成するケースです。pull-requestとreleaseでの文面が一致する前提としています。
release作成時のバージョン指定についてはインクリメントの条件もリポジトリによって異なると思われるため、とりあえず被らない想定で日付指定にしています。
on: pull_request: branches: - master types: [closed] jobs: merge: if: github.event.pull_request.merged == true runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 with: ref: ${{ github.event.pull_request.head.sha }} - name: pull-request merged run: | echo "::set-env name=release_tag::v$(date '+%Y%m%d_%H%M%S')" - name: Create Release id: create_release uses: actions/create-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: ${{ env.release_tag }} release_name: Release ${{ env.release_tag }} body: "${{github.event.pull_request.body}}" draft: false prerelease: false
必要に応じてdraft
とprerelease
を有効にするケースもありかと思います。
あとがき
if
における条件指定については、主にコンテキストでアクセスできる内容を使うケースもあると思いますが、ドキュメントでは中々中身がわからない場合にはDumpした方が早いと思いました。
- run: ${{ toJson(github) }}
Dumpした結果についてはそれぞれの精査が必要になってきますが、keyの組み合わせ(github.event.pull_request
等)で検索することで用例が見つかることも多々あります。
今回の記事がなにかの参考になれば幸いです。